package com.sojson.service.pay.wx.impl;

import java.time.LocalDateTime;
import java.util.Arrays;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sojson.config.exception.TransException;
import com.sojson.constant.Lock;
import com.sojson.dao.MemberDao;
import com.sojson.dao.OrderDepositDao;
import com.sojson.dao.TransferRecordDao;
import com.sojson.dao.UserCouponDao;
import com.sojson.entity.po.GoodSpecs;
import com.sojson.entity.po.HotelOrder;
import com.sojson.entity.po.Order;
import com.sojson.entity.po.OrderChild;
import com.sojson.entity.po.OrderDeposit;
import com.sojson.entity.po.UserCoupon;
import com.sojson.entity.vo.HotelOrderVo;
import com.sojson.enums.core.EPayStatus;
import com.sojson.enums.core.EPayType;
import com.sojson.enums.core.ERefundsStatus;
import com.sojson.enums.core.EUserCouponStatus;
import com.sojson.service.GoodSpecsService;
import com.sojson.service.HotelOrderService;
import com.sojson.service.OrderChildService;
import com.sojson.service.OrderService;
import com.sojson.service.pay.PayService;
import com.sojson.service.pay.wx.NotifyPayWxService;
import com.sojson.util.DateUtil;
import com.sojson.util.StringUtil;
import com.sojson.util.pay.wx.bean.WxResponseV3;

/**
 * 微信支付回调Service实现类
 * 
 * @author liu
 * @date 2021-03-24
 */
@Service
public class NotifyPayWxServiceImpl implements NotifyPayWxService {

    @Autowired
    private NotifyPayWxServiceImpl notifyPayWxServiceImpl;
    @Autowired
    private PayService payService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private HotelOrderService hotelOrderService;
    @Autowired
    private OrderChildService orderChildService;
    @Autowired
    private GoodSpecsService goodSpecsService;
    @Resource
    private UserCouponDao userCouponDaoImpl;
    @Resource
    private MemberDao memberDaoImpl;
    @Resource
    private OrderDepositDao orderDepositDaoImpl;
    @Resource
    private TransferRecordDao transferRecordDaoImpl;

    /**
     * 支付回调(购买)
     * 
     * @param result
     * @return
     * @throws Exception 
     */
    @Override
    public boolean goods(WxResponseV3 result) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return notifyPayWxServiceImpl.goodsGo(result);
        }
    }

    @Transactional
    public boolean goodsGo(WxResponseV3 result) throws Exception {
        // 获取订单
        Order order = payService.getOrderGoods(result.getOutTradeNo());

        Integer isPay = order.getIsPay();
        int code = EPayStatus.YES.getCode();
        // 查看订单是否已付款
        if (code == isPay) {
            // 如果已经用其他方式支付过了,并且没有保存微信的支付单号就保存
            if (order.getPayType() != EPayType.WX.getCode() && StringUtil.isBlankObject(order.getPayNoWx())) {
                Order ord = new Order();
                ord.setId(order.getId());
                ord.setPayNoWx(result.getTransactionId());
                int updatePartialById = orderService.updatePartialById(ord);
                if (updatePartialById < 1) {
                    throw new TransException("订单修改失败,请重试！");
                }
            }
            return true;
        }

        // 修改订单状态
        payService.goods(order, result.getTransactionId(), EPayType.WX);

        // 处理完成
        return true;
    }

    /**
     * 退款回调(商城)
     * 
     * @param result
     * @return
     * @throws Exception 
     */
    @Override
    public boolean goodsCancel(WxResponseV3 result) throws Exception {
        synchronized (Lock.ORDER_STATUS) {
            return payService.goodsCancel(result.getOutTradeNo(), result.getOutRefundNo(), EPayType.WX);
        }
    }

    /**
     * 支付回调(诚意金)
     * 
     * @param paramResult
     * @return
     */
    @Override
    public boolean deposit(WxResponseV3 wxResponse) {
        synchronized (Lock.ORDER_DEPOSIT_STATUS) {
            return notifyPayWxServiceImpl.depositGo(wxResponse);
        }
    }

    @Transactional
    public boolean depositGo(WxResponseV3 result) {
        // 获取订单
        OrderDeposit orderDeposit = payService.getOrderDeposit(result.getOutTradeNo());

        Integer isPay = orderDeposit.getIsPay();
        int code = EPayStatus.YES.getCode();
        // 查看订单是否已付款
        if (code == isPay) {
            // 如果已经用其他方式支付过了,并且没有保存微信的支付单号就保存
            if (orderDeposit.getPayType() != EPayType.WX.getCode()
                && StringUtil.isBlankObject(orderDeposit.getPayNoWx())) {
                Order ord = new Order();
                ord.setId(orderDeposit.getId());
                ord.setPayNoWx(result.getTransactionId());
                int updatePartialById = orderService.updatePartialById(ord);
                if (updatePartialById < 1) {
                    throw new TransException("订单修改失败,请重试！");
                }
            }
            return true;
        }

        // 修改订单状态
        payService.deposit(orderDeposit, result.getTransactionId(), EPayType.WX);

        // 处理完成
        return true;
    }

    /**
     * 退款回调(诚意金)
     * 
     * @param result
     * @return
     * @throws Exception 
     */
    @Override
    public boolean depositCancel(WxResponseV3 result) throws Exception {
        synchronized (Lock.ORDER_DEPOSIT_STATUS) {
            return payService.depositCancel(result.getOutTradeNo(), result.getOutRefundNo(), EPayType.WX);
        }
    }

    /**
     * 支付回调(酒店)
     * 
     * @param paramResult
     * @return
     * @throws Exception 
     */
    @Override
    public boolean hotel(WxResponseV3 wxResponse) throws Exception {
        synchronized (Lock.ORDER_DEPOSIT_STATUS) {
            return notifyPayWxServiceImpl.hotelGo(wxResponse);
        }
    }

    @Transactional
    public boolean hotelGo(WxResponseV3 result) throws Exception {
        // 获取订单
        HotelOrderVo orderHotel = payService.getOrderHotel(result.getOutTradeNo());

        Integer isPay = orderHotel.getIsPay();
        int code = EPayStatus.YES.getCode();
        // 查看订单是否已付款
        if (code == isPay) {
            // 如果已经用其他方式支付过了,并且没有保存微信的支付单号就保存
            if (orderHotel.getPayType() != EPayType.WX.getCode() && StringUtil.isBlankObject(orderHotel.getNoPayWx())) {
                HotelOrder ord = new HotelOrder();
                ord.setId(orderHotel.getId());
                ord.setNoPayWx(result.getTransactionId());
                int updatePartialById = hotelOrderService.updateById(ord);
                if (updatePartialById < 1) {
                    throw new TransException("订单修改失败,请重试！");
                }
            }
            return true;
        }

        // 修改订单状态
        payService.hotel(orderHotel, result.getTransactionId(), EPayType.WX);

        // 处理完成
        return true;
    }

    /**
     * 退款回调(酒店)
     * 
     * @param result
     * @return
     * @throws Exception 
     */
    @Override
    public boolean hotelCancel(WxResponseV3 result) throws Exception {
        synchronized (Lock.ORDER_DEPOSIT_STATUS) {
            return payService.hotelCancel(result.getOutTradeNo(), result.getOutRefundNo(), EPayType.WX);
        }
    }

    /**
     * 支付回调(续租)
     * 
     * @param result
     * @return
     */
    @Override
    public boolean notifyPayGoOn(WxResponseV3 result) {
        // 给主订单添加日期
        synchronized (Lock.ORDER_STATUS) {
            return notifyPayWxServiceImpl.notifyPayGoOnGo(result);
        }
    }

    @Transactional
    public boolean notifyPayGoOnGo(WxResponseV3 result) {
        // 获取订单号
        String out_trade_no = result.getOutTradeNo();

        // 查看订单是否存在
        OrderChild findByOrderSn = orderChildService.getInfoByOrderSn(out_trade_no);
        if (StringUtil.isBlankObject(findByOrderSn)) {
            throw new TransException("订单不存在！");
        }

        Integer isPay = findByOrderSn.getIsPay();
        int code = EPayStatus.YES.getCode();
        // 查看订单是否已付款
        if (code == isPay) {
            // 如果已经用其他方式支付过了,并且没有保存微信的支付单号就保存
            if (findByOrderSn.getPayType() != EPayType.WX.getCode()
                && StringUtil.isBlankObject(findByOrderSn.getPayNoWx())) {
                Order ord = new Order();
                ord.setId(findByOrderSn.getId());
                ord.setPayNoWx(result.getTransactionId());
                int updatePartialById = orderService.updatePartialById(ord);
                if (updatePartialById < 1) {
                    throw new TransException("订单修改失败,请重试！");
                }
            }
            return true;
        }

        // 修改订单状态
        OrderChild ord = new OrderChild();
        ord.updateInit();
        ord.setId(findByOrderSn.getId());
        ord.setPaySn(result.getTransactionId());
        ord.setPayNoWx(ord.getPaySn());
        ord.setIsPay(code);
        ord.setPayType(EPayType.WX.getCode());
        int updatePartialById = orderChildService.updatePartialById(ord);
        if (updatePartialById < 1) {
            throw new TransException("订单状态修改失败！");
        }

        // 给主订单添加日期
        Order findById = orderService.findById(findByOrderSn.getOrderId());
        // 天数
        Integer rentDays = findByOrderSn.getRentDays();
        LocalDateTime dateToLocalDateTime = DateUtil.dateToLocalDateTime(findById.getEndTime());
        dateToLocalDateTime = dateToLocalDateTime.plusDays(rentDays);
        Order order = new Order();
        order.updateInit();
        order.setId(findByOrderSn.getOrderId());
        order.setEndTime(DateUtil.localDateTimeToDate(dateToLocalDateTime));
        order.setRentDays(findById.getRentDays() + rentDays);
        int update = orderService.updatePartialById(order);
        if (update < 1) {
            throw new TransException("订单状态修改失败！");
        }

        // 处理完成
        return true;
    }

    /**
     * 退款回调(续签)
     * 
     * @return
     */
    @Override
    public boolean notifyPayCancelGoOn(WxResponseV3 result) {
        synchronized (Lock.ORDER_STATUS) {
            return notifyPayWxServiceImpl.notifyPayCancelGoOnGo(result);
        }
    }

    @Transactional
    public boolean notifyPayCancelGoOnGo(WxResponseV3 result) {
        int updatePartialById = 0;
        // 获取订单号
        String out_trade_no = result.getOutTradeNo();
        OrderChild findByOrderSn = null;

        // 查看订单是否存在
        findByOrderSn = orderChildService.getInfoByOrderSn(out_trade_no);
        if (StringUtil.isBlankObject(findByOrderSn)) {
            throw new TransException("订单不存在！");
        }
        Order findById = orderService.getInfo(findByOrderSn.getOrderId());

        // 查看订单是否已退款
        int code = ERefundsStatus.YES.getCode();
        if (code == findByOrderSn.getIsRefunds()) {
            return true;
        }

        // 修改订单状态
        Order ord = new Order();
        ord.setId(findByOrderSn.getId());
        ord.setIsRefunds(code);
        updatePartialById = orderService.updatePartialById(ord);

        // 修改库存
        GoodSpecs goodSpecs = new GoodSpecs();
        goodSpecs.setId(findById.getGoodSpecsId());
        goodSpecs.setStock(findById.getOrderGoods().getNum());
        int updateStock = goodSpecsService.updateStock(goodSpecs);
        if (updateStock < 1) {
            throw new TransException("修改商品库存失败！");
        }
        if (updatePartialById < 1) {
            throw new TransException("订单状态修改失败！");
        }
        // 获取优惠券编号
        String couponNos = findByOrderSn.getCouponNos();
        // 如果有用优惠券就将优惠券退回
        if (StringUtil.isNotBlankObject(couponNos)) {
            String[] split = couponNos.split(",");
            UserCoupon userCoupon = new UserCoupon();
            userCoupon.setNos(Arrays.asList(split));
            userCoupon.setStatus(EUserCouponStatus.USE_NO.getCode());
            userCouponDaoImpl.updateByNoList(userCoupon);
        }

        // 处理完成
        return true;
    }

    /**
     * 主动退款回调(购买)
     * 
     * @param result
     * @return
     */
    @Override
    public boolean notifyPayCancelInitiative(WxResponseV3 result) {
        synchronized (Lock.ORDER_STATUS) {
            return notifyPayWxServiceImpl.notifyPayCancelInitiativeGo(result);
        }
    }

    @Transactional
    public boolean notifyPayCancelInitiativeGo(WxResponseV3 result) {
        int updatePartialById = 0;
        // 获取订单号
        String out_trade_no = result.getOutTradeNo();
        Order findByOrderSn = null;

        // 查看订单是否存在
        findByOrderSn = orderService.getInfoByOrderSn(out_trade_no);
        if (StringUtil.isBlankObject(findByOrderSn)) {
            throw new TransException("订单不存在！");
        }

        // 查看订单是否已退款
        int code = ERefundsStatus.YES.getCode();
        if (code == findByOrderSn.getIsRefunds()) {
            return true;
        }

        // 修改订单状态
        Order ord = new Order();
        ord.setId(findByOrderSn.getId());
        ord.setIsRefunds(code);
        updatePartialById = orderService.updatePartialById(ord);
        if (updatePartialById < 1) {
            throw new TransException("订单状态修改失败！");
        }

        // 处理完成
        return true;
    }

    /**
     * 主动退款回调(购买)
     * 
     * @param result
     * @return
     */
    @Override
    public boolean notifyPayCancelGoOnInitiative(WxResponseV3 result) {
        synchronized (Lock.ORDER_STATUS) {
            return notifyPayWxServiceImpl.notifyPayCancelGoOnInitiativeGo(result);
        }
    }

    @Transactional
    public boolean notifyPayCancelGoOnInitiativeGo(WxResponseV3 result) {
        int updatePartialById = 0;
        // 获取订单号
        String out_trade_no = result.getOutTradeNo();
        OrderChild findByOrderSn = null;

        // 查看订单是否存在
        findByOrderSn = orderChildService.getInfoByOrderSn(out_trade_no);
        if (StringUtil.isBlankObject(findByOrderSn)) {
            throw new TransException("订单不存在！");
        }

        // 查看订单是否已退款
        int code = ERefundsStatus.YES.getCode();
        if (code == findByOrderSn.getIsRefunds()) {
            return true;
        }

        // 修改订单状态
        OrderChild ord = new OrderChild();
        ord.setId(findByOrderSn.getId());
        ord.setIsRefunds(code);
        updatePartialById = orderChildService.updatePartialById(ord);
        if (updatePartialById < 1) {
            throw new TransException("订单状态修改失败！");
        }

        // 处理完成
        return true;
    }

}